package com.fastloan.jn.mgt.product.service.impl;

import com.fastloan.jn.common.BasicServiceImpl;
import com.fastloan.jn.mgt.product.dao.JnProductApproveMapper;
import com.fastloan.jn.mgt.product.model.JnProductApprove;
import com.fastloan.jn.mgt.product.model.vo.JnProductApproveVo;
import com.fastloan.jn.mgt.product.service.JnProductApproveService;
import com.fastloan.safe.core.util.ManagerKit;
import com.fastloan.safe.mgt.user.model.CmuUser;
import com.fastloan.safe.mgt.user.service.CmuUserService;
import com.kawins.result.ResultEnum;
import com.kawins.result.ResultTo;
import com.kawins.supers.table.manager.DataTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.function.Predicate;

import static com.fastloan.jn.mgt.product.enums.JnProductEnum.PUBLISHED;
import static com.fastloan.jn.mgt.product.enums.JnProductEnum.UNPUBLISHED;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

/**
 * @author chenkai
 *         createTime 2017-10-2017/10/20 16:09
 */
@Service
public class JnProductApproveServiceImpl extends BasicServiceImpl<JnProductApprove> implements JnProductApproveService {
    @Autowired
    private JnProductApproveMapper approveMapper;

    @Autowired
    private CmuUserService cmuUserService;

    /**
     * 错误的节点数量
     */
    private static final int ERROR_NODE_COUNT = 2;

    @Override
    public ResultTo getNodeNameList(String productId) {
        JnProductApprove productApprove = new JnProductApprove();
        productApprove.setProductId(productId);
        List<JnProductApprove> temporaryList = select(productApprove)
                .parallelStream()
                .collect(toList());
        return new ResultTo().setData(temporaryList);
    }

    @Override
    public ResultTo update(JnProductApprove productApprove) {
        try {
            decisionNode(productApprove);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultTo(ResultEnum.OPERATION_FAILED, e.getMessage());
        }
        return updateByPrimaryKeySelective(productApprove) != 0 ? new ResultTo() : new ResultTo(ResultEnum.OPERATION_FAILED);
    }

    @Override
    public ResultTo add(JnProductApprove productApprove) {
        try {
            decisionNode(productApprove);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultTo(ResultEnum.OPERATION_FAILED, e.getMessage());
        }
        return insertSelective(productApprove) != 0 ? new ResultTo() : new ResultTo(ResultEnum.OPERATION_FAILED);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultTo changeApprove(String approveIds) {
        List<JnProductApprove> productApproveList = Arrays.stream(approveIds.split(","))
                .map(this::selectByPrimaryKey)
                .collect(toList());
        if (productApproveList.size() <= ERROR_NODE_COUNT) {
            throw new RuntimeException("流程必须包含开始, 结束和中间节点");
        }
        JnProductApprove productApprove = productApproveList.stream().findFirst().get();
        approveMapper.resetOrder(productApprove.getProductId());
        order(productApproveList);
        return new ResultTo();
    }


    /**
     * 设置审核顺序
     *
     * @param productApproveList
     */
    private void order(List<JnProductApprove> productApproveList) {
        int order = 0;
        JnProductApprove approve = productApproveList.parallelStream().findFirst().get();
        if (!approve.getStartNode().equals(PUBLISHED.getType())) {
            throw new RuntimeException("第一个节点必须是开始节点");
        }
        for (int i = 0; i < productApproveList.size(); i++) {
            JnProductApprove productApprove = productApproveList.get(i);
            JnProductApprove nextProductApprove;
            if (productApproveList.size() != i + 1) {
                nextProductApprove = productApproveList.get(i + 1);
            } else {
                nextProductApprove = productApproveList.get(i);
                if (!nextProductApprove.getFinalNode().equals(PUBLISHED.getType())) {
                    throw new RuntimeException("最后一个节点必须是结束节点");
                }
            }
            productApprove.setNextNodeId(nextProductApprove.getApproveId());
            productApprove.setOrderBy(order);
            updateByPrimaryKeySelective(productApprove);
            order++;
        }
    }

    @Override
    public ResultTo approveOrder(String productId) {
        JnProductApprove approve = new JnProductApprove();
        approve.setProductId(productId);
        List<JnProductApprove> productApproveList = select(approve);
        List<JnProductApprove> list = productApproveList.parallelStream()
                .filter(productApprove -> productApprove.getOrderBy() != null)
                .sorted(Comparator.comparing(JnProductApprove::getOrderBy))
                .collect(toList());
        List<JnProductApprove> collect = productApproveList.parallelStream()
                .filter(productApprove -> productApprove.getOrderBy() == null)
                .collect(toList());
        return new ResultTo().setData("order", list).setData("unsorted", collect);
    }

    @Override
    public Integer insertList(List<JnProductApprove> list) {
        return approveMapper.insertList(list);
    }

    @Override
    public ResultTo getNodeInfo(String approveId) {
        JnProductApprove approve = selectByPrimaryKey(approveId);
        JnProductApproveVo productApproveVo = new JnProductApproveVo();
        List<String> stringList = Arrays.stream(approve.getAssessingOfficer().split(",")).collect(toList());
        Example example = new Example(CmuUser.class);
        example.createCriteria().andIn("id", stringList);
        List<CmuUser> cmuUsers = cmuUserService.selectByExample(example);
        productApproveVo.setCmuUsers(cmuUsers);
        productApproveVo.setJnProductApprove(approve);
        return new ResultTo().setData(productApproveVo);
    }

    @Override
    @DataTable(name = "nodePageList")
    public List<JnProductApprove> nodePageList(Map<String, Object> map) {
        Example example = new Example(JnProductApprove.class);
        example.createCriteria().andEqualTo("productId", map.get("productId"));
        List<JnProductApprove> jnProductApproveList = selectByExample(example);
        jnProductApproveList.stream()
                .filter(jnProductApprove -> jnProductApprove.getAssessingOfficer() != null)
                .forEach(jnProductApprove -> {
                    String assessingOfficer = jnProductApprove.getAssessingOfficer();
                    List<String> stringList = Arrays.stream(assessingOfficer.split(",")).collect(toList());
                    Example example2 = new Example(CmuUser.class);
                    example2.createCriteria().andIn("id", stringList);
                    List<CmuUser> cmuUsers = cmuUserService.selectByExample(example2);
                    String userCame = cmuUsers.parallelStream().map(CmuUser::getCname).collect(joining(","));
                    jnProductApprove.setApproveUserName(userCame);
                });
        return jnProductApproveList;
    }

    /**
     * 新增/更新节点验证
     *
     * @param productApprove
     */
    private void decisionNode(JnProductApprove productApprove) {
        JnProductApprove approve = new JnProductApprove();
        approve.setProductId(productApprove.getProductId());
        List<JnProductApprove> productApproveList = select(approve);
        JnProductApprove beForeApprove;
        boolean flag = true;
        boolean flag1 = true;
        if (productApprove.getApproveId() != null) {
            beForeApprove = selectByPrimaryKey(productApprove.getApproveId());
            flag = beForeApprove.getStartNode().equals(UNPUBLISHED.getType());
            flag1 = beForeApprove.getFinalNode().equals(UNPUBLISHED.getType());
        }
        //新增/更新起始节点
        if (flag && productApprove.getStartNode().equals(PUBLISHED.getType())) {
            if (stream(productApproveList, approves -> approves.getStartNode().equals(PUBLISHED.getType())) > 0) {
                throw new RuntimeException("已存在开始节点");
            }
        }
        //新增/更新结束节点
        if (flag1 && productApprove.getFinalNode().equals(PUBLISHED.getType())) {
            if (stream(productApproveList, approves -> approves.getFinalNode().equals(PUBLISHED.getType())) > 0) {
                throw new RuntimeException("已存在结束节点");
            }
        }
    }

    private <T> long stream(List<T> list, Predicate<T> predicate) {
        return list.parallelStream()
                .filter(predicate)
                .count();
    }

}
